#pragma once
#include "afxwin.h"

#include "DisplaySettings.h"
#include "TerminalSettings.h"
#include "FrameBuffer.h"
#include "Coordinate.h"
#include "AnsiCommand.h"

#define WM_TEXTRECEIVED (WM_USER+100)
#define WM_ANSICOMMAND (WM_USER+101)

[event_source(native)]
class CBbsConsole : public CWnd
{
	DECLARE_DYNAMIC(CBbsConsole)

public:
	CBbsConsole(void);
	~CBbsConsole(void);

	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

	const int Rows() const;
	const int Columns() const;

	void GetPreferredWindowSize(CSize& size);
	void RefreshDisplaySettings();
	void Reset();
	void WriteText(unsigned char* pStr, int n);
	void ExecuteAnsiCommand(const CAnsiCommand& command);

	__event void OnInputReceivedEvent(unsigned char* buffer, int count);

protected:
	CDisplaySettings& displaySettings;
	CTerminalSettings& terminalSettings;

	LPWSTR wideCharConversionBuffer;
	int wideCharConversionCount;

	UINT_PTR blinkingTimer;
	bool blinkingToggle;

	UINT codepage;

#pragma region Cached resources for drawing. 
	CFont normalFont;
	CFont underlineFont;

	int charWidth;
	int charHeight;
#pragma endregion These values need to be created upon creation and re-created when DisplaySettings change.

#pragma region Snap shot of the console
	CFrameBuffer frameBuffer;
	
	CCoordinate savedCursorPosition;
	CCoordinate cursorPosition;
	bool showCursor;

	AnsiColor foregroundColor;
	AnsiColor backgroundColor;
	unsigned char attributes;
#pragma endregion

	void ExecuteSelectGraphicRendition(int code);
	void ExecuteEraseInDisplay(int param);
	void ExecuteEraseLine(int param);
	bool ToWideChar(LPCSTR inputBuffer, int inputCount, LPWSTR& outputBuffer, int& outputCount);
	void SetCharAt(int row, int column, wchar_t ch);
	void PaintSquare(CPaintDC &dc, int row, int column);
	void InvalidateSquare(const CCoordinate& pt);
	void InvalidateSquare(int row, int column);
	void InvalidateBlock(int top, int left, int bottom, int right);
	bool IsSelected(int row, int column);

	static bool IsWide(wchar_t);

public:
	DECLARE_MESSAGE_MAP()

	afx_msg void OnTimer(UINT_PTR nIDEvent);
	afx_msg void OnClose();
	afx_msg int OnCreate(LPCREATESTRUCT);
	afx_msg void OnPaint();
	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg LRESULT OnTextReceived(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnAnsiCommand(WPARAM, LPARAM lParam);
	afx_msg LRESULT OnImeStartComposition(WPARAM, LPARAM);
};
